<?php

/**
 * Obiekt języka
 *
 */
class Rapide_Language
{
	private static $_oInstance;
	private
		$_sLanguage,
		$_sLanguageDir,
		$_aLanguage = array();

	/**
	 * Konstruuje obiekt inizjalizując go nazwą podanego języka
	 *
	 * @param string $sLanguage nazwa języka będąca nazwą katalogu z plikami językowymi
	 * @throws Rapide_Language_Exception jeżeli podany język nie istnieje
	 * @throws Rapide_Language_Exception jeżeli tablica języka nie istnieje w głównym pliku językowym
	 */
	private function __construct($sLanguage)
	{
		$sLanguage = ucfirst($sLanguage);

		$sLanguageFile = _DIR_LANGUAGES . '/' . $sLanguage . '.php';

		if(!is_readable($sLanguageFile))
		{
			$sError = sprintf('Language %s does not exist', $sLanguage);
			throw new Rapide_Language_Exception($sError);
		}

		require $sLanguageFile;

		if(!isset($aLang))
		{
			$sError = sprintf('Array for language %s does not exist', $sLanguage);
			throw new Rapide_Language_Exception($sError);
		}

		$this->_sLanguage		= $sLanguage;
		$this->_sLanguageDir = _DIR_LANGUAGES . '/' . $sLanguage . '/';
		$this->_aLanguage		= $aLang;
	}

	/**
	 * Inicjalizuje obiekt podanym językiem
	 *
	 * @param string $sLanguage
	 * @return Rapide_Language obiekt języka
	 * @throws Rapide_Language_Exception jeżeli obiekt był już wcześniej inicjalizowany
	 */
	public static function init($sLanguage)
	{
		if(self::$_oInstance instanceof self)
		{
			$sError = 'Language has been initialized';
			throw new Rapide_Language_Exception($sError);
		}

		self::$_oInstance = new Rapide_Language($sLanguage);

		return self::$_oInstance;
	}

	/**
	 * Zwraca instację obiektu
	 *
	 * @return Rapide_Language
	 * @throws Rapide_Language_Exception jeżeli obiekt nie został wcześniej zainicjalizowany
	 */
	public static function getInstance()
	{
		if(!self::$_oInstance instanceof self)
		{
			$sError = 'Language has not been initialized yet';
			throw new Rapide_Language_Exception($sError);
		}

		return self::$_oInstance;
	}

	/**
	 * Zwraca tłumaczenie odpowiadające podanym parametrom
	 * 
	 * Metoda przyjmuje listę parametrów w taki sposób, by kolejne parametry odzwierciedlały
	 * kolejne wpisy w katalogu językowym. Na przykład:
	 * 
	 * <code>
	 * $oLang->get('Katalog1', 'Katalog2', 'Plik', 'Tablica1', 'Klucz');
	 * </code>
	 * 
	 * Obiekt zwróci tłumaczenie dla klucza 'Klucz', z tablicy 'Tablica1'. Ta natomiast znajduje
	 * się w Katalog1/Katalog2/Plik.php
	 *
	 * @return string tłumaczenie lub null jeżeli nie znaleziono tłumaczenia
	 */
	public function get()
	{
		$aArgs = func_get_args();

		$sTranslation = call_user_func_array(array($this, '_get'), $aArgs);

		if(is_null($sTranslation))
		{
			call_user_func_array(array($this, '_load'), $aArgs);
		}

		return call_user_func_array(array($this, '_get'), $aArgs);
	}

	private function _get()
	{
		$aArgs = func_get_args();
		$aLanguage = $this->_aLanguage;

		$iArgsCount = count($aArgs);

		$sTranslation = null;

		for($i = 0; $i < $iArgsCount; $i++)
		{
			if(isset($aLanguage[$aArgs[$i]]))
			{
				if(is_array($aLanguage[$aArgs[$i]]) && $i == $iArgsCount - 1)
					$sTranslation = $aLanguage[$aArgs[$i]];
				else if(is_array($aLanguage[$aArgs[$i]]))
				{
					$aLanguage = $aLanguage[$aArgs[$i]];
					continue;
				}
				else
					$sTranslation = $aLanguage[$aArgs[$i]];
			}
		}

		return $sTranslation;
	}

	private function _load()
	{
		$aArgs = func_get_args();

		$sDir = $this->_sLanguageDir;

		foreach($aArgs as $sParameter)
		{
			$sLanguageFile = $sDir . basename($sParameter) . '.php';
			$sDir = $sDir . basename($sParameter) . '/';

			if(file_exists($sLanguageFile))
			{
				$this->_loadFile($sLanguageFile);
				break;
			}
			elseif(is_dir($sDir))
				continue;
			else
				break;
		}
	}

	private function _loadFile($sFile)
	{
		if(!is_readable($sFile))
		{
			$sError = sprintf('Language %s for %s does not exist',
												$this->_sLanguage, $sFile);

			throw new Rapide_Language_Exception($sError);
		}

		require $sFile;

		if(!is_array($aLang))
		{
			$sError = sprintf('Array for language %s in file %s
												 does not exist', $this->_sLanguage, $sFile);

			throw new Rapide_Language_Exception($sError);
		}

		$sRelativeFile = substr($sFile, strlen($this->_sLanguageDir));

		$sLoadedEntries = substr($sRelativeFile, 0, strlen($sRelativeFile) - 4); // Drop .php

		$aLoadedEntries = explode('/', $sLoadedEntries);

		$aLoadedLanguage = array();
		$aTemp = $aLang;

		for($i = count($aLoadedEntries) - 1; $i >= 0; $i--)
		{
			$aLoadedLanguage = array();
			$aLoadedLanguage[$aLoadedEntries[$i]] =	$aTemp;
			$aTemp = $aLoadedLanguage;
		}

		$this->_aLanguage = array_merge($this->_aLanguage, $aLoadedLanguage);
	}

	/**
	 * Zwraca całą tablicę z danymi językowymi
	 *
	 * @return array
	 */
	public function getArray()
	{
		return $this->_aLanguage;
	}
}

?>